package com.net.web.server.strategy.impl;

import com.net.common.entity.CacheBean;
import com.net.common.entity.HttpCarrier;
import com.net.common.entity.Message;
import com.net.common.util.CloseableUtils;
import com.net.common.util.ThreadPoolFactory;
import com.net.web.server.config.ServerConfig;
import com.net.web.server.strategy.IMessageStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

import static com.net.web.server.config.ServerMapContext.cacheMap;
import static com.net.web.server.config.ServerMapContext.socketWanMap;
import static com.net.common.constant.Constant.HttpMethod.GET;
import static com.net.common.constant.Constant.MessageType.FORWARD;

/**
 * 处理转发消息
 *
 * @author hjh
 */
@Service(FORWARD)
@Slf4j
public class MessageForwardImpl implements IMessageStrategy<Message> {
    @Autowired
    private ServerConfig serverConfig;

    @Override
    public void execute(Message message, Socket clientSocket, Long sessionId) {
        Socket socketWan = socketWanMap.get(message.getSessionId()).get(message.getSocketWanId());
        if (Objects.isNull(socketWan)) {
            log.info("socketWan 已经被关闭 sessionId:{},socketWanId:{}", message.getSessionId(), message.getSocketWanId());
            return;
        }

        ThreadPoolFactory.execute(() -> {
            OutputStream outputStream = null;
            try {
                outputStream = socketWan.getOutputStream();
                outputStream.write(message.getBody());
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                CloseableUtils.close(socketWanMap.get(message.getSessionId()).remove(message.getSocketWanId()), outputStream);
            }
        });

        // 添加缓存
        addCacheMap(message, sessionId);
    }

    @Override
    public void afterPropertiesSet() {
        MessageContext.register(FORWARD, this);
    }

    /**
     * 添加缓存
     *
     * @param message 消息实体
     */
    private void addCacheMap(Message message, Long sessionId) {
        // 是否开启缓存
        if (!serverConfig.isEnableCache()) {
            return;
        }

        HttpCarrier carrier = message.getCarrier();

        if (Objects.isNull(carrier) || StringUtils.isBlank(carrier.getCacheKey())) {
            return;
        }

        if ((cacheMap.containsKey(sessionId) && cacheMap.get(sessionId).containsKey(carrier.getCacheKey())) || !GET.equals(carrier.getMethod())) {
            return;
        }
        // 超过800毫秒就缓存
        if (System.currentTimeMillis() - carrier.getTimestamp() < 800) {
            return;
        }

        // 加入缓存
        if (cacheMap.containsKey(sessionId)) {
            cacheMap.get(sessionId).put(carrier.getCacheKey(), new CacheBean(message.getBody()));
            return;
        }

        Map<String, CacheBean> cacheBeanMap = new ConcurrentHashMap<>();
        cacheBeanMap.put(carrier.getCacheKey(), new CacheBean(message.getBody()));
        cacheMap.put(sessionId, cacheBeanMap);
    }
}
